package com.netposa.datawarehouse.aggregator.config;

import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import com.netposa.datawarehouse.aggregator.web.model.ModuleTable;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
public class AggregatorAutoConfiguration {
   private static final Logger log = LoggerFactory.getLogger(AggregatorAutoConfiguration.class);

   @Bean(
      destroyMethod = "shutdownNow"
   )
   public ForkJoinPool forkJoinPool() {
      return new ForkJoinPool(Runtime.getRuntime().availableProcessors());
   }

   @Bean(
      destroyMethod = "shutdownNow"
   )
   public ExecutorService executor() {
      return Executors.newCachedThreadPool();
   }

   @Bean
   @Primary
   public Gson gson() {
      return new GsonBuilder().serializeNulls().registerTypeAdapter(Double.class, (Object)new JsonSerializer<Double>(){

         public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
            if (src == (double)src.longValue()) {
               return new JsonPrimitive((Number)src.longValue());
            }
            return new JsonPrimitive((Number)src);
         }
      }).registerTypeAdapter(new TypeToken<Map<String, Object>>(){}.getType(), (Object)new MapTypeAdapter()).create();
   }

   @Bean
   public ModuleTable moduleTable() {
      log.info("初始化子集服务模块注册列表开始...");
      ModuleTable moduleTable = ModuleTable.getInstance();
      moduleTable.init();
      log.info("初始化子集服务模块注册列表完成...");
      return moduleTable;
   }

   public static class MapTypeAdapter extends TypeAdapter {
      public Object read(JsonReader in) throws IOException {
         JsonToken token = in.peek();
         switch (token) {
            case BEGIN_ARRAY:
               List list = new ArrayList();
               in.beginArray();

               while(in.hasNext()) {
                  list.add(this.read(in));
               }

               in.endArray();
               return list;
            case BEGIN_OBJECT:
               Map map = new LinkedTreeMap();
               in.beginObject();

               while(in.hasNext()) {
                  map.put(in.nextName(), this.read(in));
               }

               in.endObject();
               return map;
            case STRING:
               return in.nextString();
            case NUMBER:
               double dbNum = in.nextDouble();
               if (dbNum > 9.223372036854776E18) {
                  return dbNum;
               } else {
                  long lngNum = (long)dbNum;
                  if (dbNum == (double)lngNum) {
                     return lngNum;
                  }

                  return dbNum;
               }
            case BOOLEAN:
               return in.nextBoolean();
            case NULL:
               in.nextNull();
               return null;
            default:
               throw new IllegalStateException();
         }
      }

      public void write(JsonWriter out, Object value) throws IOException {
      }
   }
}
